package com.tangyuan.common.util;

import com.tangyuan.common.constant.Constants;

import java.security.SecureRandom;
import java.util.Collection;
import java.util.Map;

/**
 * @描述: 字符串工具类
 * @Author: TangYuan
 * @Date: 2024/9/24 上午9:22
 */
public class StringUtils extends org.apache.commons.lang3.StringUtils {
    
    /** 空字符串 */
    private static final String NULL_STR = "";
    
    /** 下划线 */
    private static final char SEPARATOR = '_';
    
    /** 星号 */
    private static final char ASTERISK = '*';
    
    
    /**
     * 获取参数不为空值
     * @param value        要判断的value
     * @param defaultValue 为空的默认值
     * @return T 返回值
     */
    public static <T> T nvl(T value, T defaultValue) {
        return value != null ? value : defaultValue;
    }
    
 
    /**
     * 判断一个Collection是否为空， 包含List，Set，Queue
     * @param coll 要判断的Collection
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(Collection<?> coll) {
        return isNull(coll) || coll.isEmpty();
    }
    /**
     * 判断一个Collection是否非空，包含List，Set，Queue
     * @param coll 要判断的Collection
     * @return true：非空 false：空
     */
    public static boolean isNotEmpty(Collection<?> coll) {
        return !isEmpty(coll);
    }
    
    
    /**
     * 判断一个对象数组是否为空
     * @param objects 要判断的对象数组
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(Object[] objects) {
        return isNull(objects) || (objects.length == 0);
    }
    /**
     * 判断一个对象数组是否非空
     * @param objects 要判断的对象数组
     * @return true：非空 false：空
     */
    public static boolean isNotEmpty(Object[] objects) {
        return !isEmpty(objects);
    }
    
    
    /**
     * 判断一个Map是否为空
     * @param map 要判断的Map
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(Map<?, ?> map) {
        return isNull(map) || map.isEmpty();
    }
    /**
     * 判断一个Map是否为空
     * @param map 要判断的Map
     * @return true：非空 false：空
     */
    public static boolean isNotEmpty(Map<?, ?> map) {
        return !isEmpty(map);
    }
    
    
    /**
     * 判断一个字符串是否为空串
     * @param str String
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(String str) {
        return isNull(str) || NULL_STR.equals(str.trim());
    }
    /**
     * 判断一个字符串是否为非空串
     * @param str String
     * @return true：非空串 false：空串
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }
    
    
    /**
     * 判断一个对象是否为空
     * @param object Object
     * @return true：为空 false：非空
     */
    public static boolean isNull(Object object) {
        return object == null;
    }
    /**
     * 判断一个对象是否非空
     * @param object Object
     * @return true：非空 false：空
     */
    public static boolean isNotNull(Object object) {
        return !isNull(object);
    }
    
    
    /**
     * 去空格
     */
    public static String trim(String str) {
        return (str == null ? "" : str.trim());
    }
    
    /**
     * 是否为http(s)://开头
     * @param link 链接
     * @return 结果
     */
    public static boolean isHttp(String link) {
        return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
    }
    
    /**
     * 截取字符串
     * @param str   字符串
     * @param start 开始
     * @return 结果
     */
    public static String substring(final String str, int start) {
        
        if (str == null || start > str.length()) {
            return NULL_STR;
        }
        if (start < 0) {
            start = 0;
        }
        return str.substring(start);
    }
    
    /**
     * 截取字符串
     * @param str   字符串
     * @param start 开始
     * @param end   结束
     * @return 结果
     */
    public static String substring(final String str, int start, int end) {
        
        if (str == null || start > end) {
            return NULL_STR;
        }
        if (start < 0) {
            start = 0;
        }
        if (end < 0) {
            end = 0;
        }
        if (end > str.length()) {
            end = str.length();
        }
        return str.substring(start, end);
    }
    
    /**
     * 替换指定字符串的指定区间内字符为"*"
     * @param str          字符串
     * @param startInclude 开始位置（包含）
     * @param endExclude   结束位置（不包含）
     * @return 替换后的字符串
     */
    public static String hide(CharSequence str, int startInclude, int endExclude) {
        
        final int strLength = str.length();
        
        // 如果（空字符串 || 起始位置大于字符串长度 || 起始位置大于结束位置）不替换
        if (isEmpty(str) || startInclude > strLength || startInclude > endExclude) {
            return NULL_STR;
        }
        // 结束位置大于字符串长度，截取到字符串长度
        if (endExclude > strLength) {
            endExclude = strLength;
        }
        
        // 进行替换操作
        final char[] chars = new char[strLength];
        for (int i = 0; i < strLength; i++) {
            if (i >= startInclude && i < endExclude) {
                chars[i] = ASTERISK;
            } else {
                chars[i] = str.charAt(i);
            }
        }
        return new String(chars);
    }
    
    /**
     * 字符串左补齐。如果原始字符串s长度大于size，则只保留最后size个字符。
     * @param s    原始字符串
     * @param size 字符串指定长度
     * @param c    用于补齐的字符
     * @return 返回指定长度的字符串，由原字符串左补齐或截取得到。
     */
    public static String makeUpForIt(final String s, final int size, final char c) {
        
        final StringBuilder sb = new StringBuilder(size);
        
        if (s != null) {
            final int len = s.length();
            if (s.length() <= size) {
                sb.append(String.valueOf(c).repeat(size - len));
                sb.append(s);
            } else {
                return s.substring(len - size, len);
            }
        } else {
            sb.append(String.valueOf(c).repeat(Math.max(0, size)));
        }
        return sb.toString();
    }
    
    /**
     * 获取随机位数的字符串
     * @param length 长度
     * @return {@link java.lang.String}
     */
    public static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        SecureRandom random = new SecureRandom();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
}
